home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
gfx
/
pbm
/
pnmtopng.lha
/
src
/
pnmtopng.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-15
|
9KB
|
351 lines
/* pnmtopng.c - read a portable anymap and produce Public Networks Graphic file
**
** derived from pnmtorast.c (c) 1990,1991 by Jef Poskanzer
**
** Copyright (C) 1995 by Alexander Lehmann <alex@hal.rhein-main.de>
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include "pnm.h"
#include "png.h"
#include "ppmcmap.h"
#define MAXCOLORS 256
static int verbose = 0;
int
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
xel** xels;
xel p;
colorhist_vector chv;
colorhash_table cht;
int argn, rows, cols, format, i;
int depth, colors;
xelval maxval;
int interlace, downscale;
double scaleval;
int x,y;
int gray;
int mayscale;
png_struct *png_ptr = malloc(sizeof (png_struct));
png_info *info_ptr = malloc(sizeof (png_info));
png_color palette[MAXCOLORS];
png_byte *line;
png_byte *pp;
int pass;
int color;
char* usage = "[-interlace] [-downscale] [pnmfile]";
pnm_init( &argc, argv );
argn = 1;
interlace=0;
downscale=0;
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-verbose", 2 ) )
verbose=1;
else
if ( pm_keymatch( argv[argn], "-interlace", 2 ) )
interlace=1;
else
if ( pm_keymatch( argv[argn], "-downscale", 2 ) )
downscale=1;
else
pm_usage( usage );
++argn;
}
if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;
if ( argn != argc )
pm_usage( usage );
xels = pnm_readpnm( ifp, &cols, &rows, &maxval, &format );
pm_close( ifp );
/* first of all, check if we have a grayscale written as PPM */
gray=1;
if(PNM_FORMAT_TYPE(format)==PPM_TYPE) {
for(x=0;x<cols;x++)
for(y=0;y<rows;y++) {
p=xels[y][x];
if(PPM_GETR(p)!=PPM_GETG(p) || PPM_GETG(p)!=PPM_GETB(p)) {
gray=0;
goto break2a;
}
}
break2a:
if(gray) format=PGM_TYPE;
}
/* handle `odd' maxvalues */
if(PNM_FORMAT_TYPE(format)!=PBM_TYPE) {
if(maxval>65535 && !downscale)
pm_error("can only handle files up to 16 bit (use -downscale to override");
if(maxval!=255 && maxval!=65535 &&
(PNM_FORMAT_TYPE(format)!=PGM_TYPE || (maxval!=1 && maxval!=3 &&
maxval!=15))) {
if(maxval<255) {
pm_message("rescaling to 8 bit");
scaleval=255.0;
} else {
pm_message("rescaling to 16 bit");
scaleval=65535.0;
}
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
PPM_DEPTH(p, xels[y][x], maxval, scaleval);
xels[y][x]=p;
}
maxval=scaleval;
}
}
/* check for 16 bit entries which are just scaled 8 bit entries, e.g.
when converting a 8 bit palette TIFF to ppm */
if(PNM_FORMAT_TYPE(format)!=PBM_TYPE && maxval==65535) {
mayscale=1;
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
p=xels[y][x];
if(PNM_FORMAT_TYPE(format)==PGM_TYPE ?
(PNM_GET1(p)&0xff)*0x101!=PNM_GET1(p) :
(PPM_GETR(p)&0xff)*0x101!=PPM_GETR(p) ||
(PPM_GETG(p)&0xff)*0x101!=PPM_GETG(p) ||
(PPM_GETB(p)&0xff)*0x101!=PPM_GETB(p)) {
mayscale=0;
goto break2b;
}
}
break2b:
if(mayscale) {
pm_message("scaling to 8 bit (superflous 16 bit data)");
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
p=xels[y][x];
if(PNM_FORMAT_TYPE(format)==PGM_TYPE) {
PNM_ASSIGN1(xels[y][x], PNM_GET1(p)&0xff);
} else {
PPM_ASSIGN(xels[y][x], PPM_GETR(p)&0xff, PPM_GETG(p)&0xff,
PPM_GETB(p)&0xff);
}
}
maxval=255;
}
}
/* now the same thing for bit depth 4, 2 and 1, only for grayscale pics */
if(PNM_FORMAT_TYPE(format)==PGM_TYPE && maxval==255) {
mayscale=1;
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
if((PNM_GET1(xels[y][x])&0xf)*0x11!=PNM_GET1(xels[y][x]))
mayscale=0;
goto break2c;
}
break2c:
if(mayscale) {
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
PNM_ASSIGN1(xels[y][x], PNM_GET1(xels[y][x])&0xf);
}
maxval=15;
}
}
if(PNM_FORMAT_TYPE(format)==PGM_TYPE && maxval==15) {
mayscale=1;
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
if((PNM_GET1(xels[y][x])&3)*5!=PNM_GET1(xels[y][x]))
mayscale=0;
goto break2d;
}
break2d:
if(mayscale) {
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
PNM_ASSIGN1(xels[y][x], PNM_GET1(xels[y][x])&3);
}
maxval=3;
}
}
if(PNM_FORMAT_TYPE(format)==PGM_TYPE && maxval==3) {
mayscale=1;
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
if((PNM_GET1(xels[y][x])&1)*3!=PNM_GET1(xels[y][x]))
mayscale=0;
goto break2e;
}
break2e:
if(mayscale) {
for(y=0;y<rows;y++)
for(x=0;x<cols;x++) {
PNM_ASSIGN1(xels[y][x], PNM_GET1(xels[y][x])&1);
}
maxval=1;
}
}
/* Figure out the proper depth and colormap. */
switch ( PNM_FORMAT_TYPE(format) ) {
case PPM_TYPE:
if(maxval==255) {
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( xels, cols, rows, MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 ) {
pm_message("Too many colors - proceeding to write a 24-bit non-mapped" );
pm_message("image file. If you want 8 bits, try doing a 'ppmquant %d'.",
MAXCOLORS );
depth = 8;
} else {
pm_message( "%d colors found", colors );
depth=8;
if(colors<=16) depth=4;
if(colors<=4) depth=2;
if(colors<=2) depth=1;
}
} else {
depth=16;
}
break;
case PGM_TYPE:
if(maxval==65535)
depth=16;
else if(maxval==255)
depth=8;
else if(maxval==15)
depth=4;
else if(maxval==3)
depth=2;
else if(maxval==1)
depth=1;
else
pm_error("(can't happen) undefined maxvalue");
break;
default:
depth = 1;
break;
}
if(verbose)
pm_message("writing a %d bit %s file%s", depth,
PNM_FORMAT_TYPE(format)!=PPM_TYPE?"gray":(chv!=NULL?"palette":"rbg"),
interlace ? "(interlaced)" : "");
/* now write the file */
if(!setjmp(png_ptr->jmpbuf)) {
png_write_init(png_ptr);
png_info_init(info_ptr);
png_init_io(png_ptr, stdout);
info_ptr->width=cols;
info_ptr->height=rows;
info_ptr->bit_depth=depth;
if(PNM_FORMAT_TYPE(format)==PPM_TYPE) {
info_ptr->color_type=chv!=NULL ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB;
} else {
info_ptr->color_type=PNG_COLOR_TYPE_GRAY;
}
info_ptr->interlace_type=interlace;
if(info_ptr->color_type==PNG_COLOR_TYPE_PALETTE) {
for(i=0;i<MAXCOLORS;i++) {
palette[i].red=PPM_GETR(chv[i].color);
palette[i].green=PPM_GETG(chv[i].color);
palette[i].blue=PPM_GETB(chv[i].color);
}
info_ptr->palette=palette;
info_ptr->num_palette=colors;
info_ptr->valid |= PNG_INFO_PLTE;
cht = ppm_colorhisttocolorhash( chv, colors );
ppm_freecolorhist( chv );
}
png_write_info(png_ptr, info_ptr);
png_set_packing(png_ptr);
line=malloc(cols*6);
for(pass=0;pass<png_set_interlace_handling(png_ptr);pass++) {
for(y=0;y<rows;y++) {
pp=line;
for(x=0;x<cols;x++) {
p=xels[y][x];
if(info_ptr->color_type==PNG_COLOR_TYPE_GRAY) {
if(depth==16) {
*pp++=PNM_GET1(p)>>8;
}
*pp++=PNM_GET1(p)&0xff;
} else if(info_ptr->color_type==PNG_COLOR_TYPE_PALETTE) {
color = ppm_lookupcolor( cht, &p);
*pp++=color;
} else {
if(depth==16) {
*pp++=PPM_GETR(p)>>8;
}
*pp++=PPM_GETR(p)&0xff;
if(depth==16) {
*pp++=PPM_GETG(p)>>8;
}
*pp++=PPM_GETG(p)&0xff;
if(depth==16) {
*pp++=PPM_GETB(p)>>8;
}
*pp++=PPM_GETB(p)&0xff;
}
}
png_write_row(png_ptr, line);
}
}
png_write_end(png_ptr, info_ptr);
png_write_destroy(png_ptr);
free(png_ptr);
free(info_ptr);
} else {
pm_error("setjmp returns error condition");
free(png_ptr);
free(info_ptr);
exit(1);
}
exit( 0 );
}